package irisext

import (
	"fmt"
	"path/filepath"
	"strconv"
	"time"

	"gitee.com/terender/sfw/rlog"
	"github.com/kataras/iris/v12"
)

// AccessLogger 访问日志工具
type AccessLogger struct {
	file         string
	withRequest  bool
	withResponse bool
}

// WithRequest 访问日志是否包含请求正文
func (l *AccessLogger) WithRequest(with bool) { l.withRequest = with }

// WithResponse 访问日志是否包含应答正文
func (l *AccessLogger) WithResponse(with bool) { l.withResponse = with }

// NewLogger creates and returns a new access logger
func NewLogger(file string) *AccessLogger {
	_, file = filepath.Split(file)
	l := &AccessLogger{
		file: file,
	}
	return l
}

// Serve serves the middleware
func (l *AccessLogger) ServeHTTP(ctx iris.Context) {
	startTime := time.Now()

	var req string
	if l.withRequest {
		req = string(cachedBody(ctx))
	}
	if l.withResponse {
		ctx.Record()
	}

	ctx.Next()

	latency := time.Since(startTime)
	status := strconv.Itoa(ctx.GetStatusCode())
	ip := ctx.RemoteAddr()
	method := ctx.Method()
	proto := ctx.Request().Proto
	host := ctx.Request().Host
	path := ctx.Request().RequestURI
	//path = ctx.Request().URL.String()
	//path = ctx.Path()

	// no new line, the framework's logger is responsible how to render each log.
	line := fmt.Sprintf("%v %4v %s %s %s %s %s", status, latency, ip, method, proto, host, path)
	if l.withRequest {
		line += fmt.Sprintf("\n  Request: %s", req)
	}
	if l.withResponse {
		line += fmt.Sprintf("\n  Response: %s", string(ctx.Recorder().Body()))
	}
	rlog.Logger(l.file).LogRaw(line)
}

type stringUnmarshaler struct{}

func (m stringUnmarshaler) Unmarshal(data []byte, outPtr interface{}) error {
	out, ok := outPtr.(*string)
	if !ok {
		return fmt.Errorf(`Input not a *string`)
	}
	*out = string(data)
	return nil
}
